package org.testis.orm.refinedclasses;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.orm.PersistentException;
import org.testis.orm.classes.T_test_label;
import org.testis.orm.classes.T_test_labelpairs;
import org.testis.orm.classes.T_test_stepcontainer;
import org.testis.orm.refinedclasses.TestDesignTreeRefined.TestDesignTreeParameters;
import org.testis.utils.middleware.LabelDataHandler;
import org.testis.utils.middleware.LabelUtils;
import org.testis.utils.middleware.TestDesign;

/**
 * 
 * @author Cahit Emir Erel
 */
public class TestCaseRefined extends DesignPart implements ILabelContainer {

    private T_test_stepcontainer m_reference;
    public static final String DEFAULT_TYPE = "Regression";

    public TestCaseRefined(T_test_stepcontainer reference) {
	setReference(reference);
    }

    @Override
    synchronized public TestCaseRefined createRefinedDatabaseCopy()
	    throws PersistentException {
	return new TestCaseRefined(createDatabaseCopy());
    }

    private T_test_stepcontainer createDatabaseCopy()
	    throws PersistentException {
	T_test_stepcontainer newContainer = new T_test_stepcontainer();
	newContainer.setContainerTypeId(this.getReference()
		.getContainerTypeId());
	newContainer.setDescription(this.getReference().getDescription());
	newContainer.setName(this.getReference().getName());
	if (newContainer.save()) {
	    return newContainer;
	} else {
	    throw new PersistentException(
		    "Unable to create database copy of Test Case (t_test_stepcontainer table)");
	}
    }

    @Override
    public String toString(TestDesignTreeNode treeNode) {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append(this.toString());
	    buffer.append("\nCritical: "
		    + treeNode.getReference().getParameterBooleanValue(
			    TestDesignTreeParameters.Critical.name()));
	    buffer.append("\nRun Always: "
		    + treeNode.getReference().getParameterBooleanValue(
			    TestDesignTreeParameters.RunAlways.name()));
	    buffer.append("\nThread Pool Size: "
		    + treeNode.getReference().getParameterIntValue(
			    TestDesignTreeParameters.ThreadPoolSize.name()));
	    buffer.append("\nInvocation Count: "
		    + treeNode.getReference().getParameterIntValue(
			    TestDesignTreeParameters.InvocationCount.name()));
	    buffer.append("\nSuccess Percentage: "
		    + treeNode.getReference().getParameterIntValue(
			    TestDesignTreeParameters.SuccessPercentage.name()));
	    buffer.append("\n\n\nLabels: ");
	    T_test_label[] labels = getLabelsAsArray();
	    if (labels != null && labels.length > 0) {
		for (int i = 0; i < labels.length; i++) {
		    buffer.append("\n\t" + labels[i].getName());
		}
	    } else {
		buffer.append("\tNo labels found");
	    }
	    return buffer.toString();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    @Override
    public String toString() {
	try {
	    StringBuffer buffer = new StringBuffer();
	    buffer.append("Type: "
		    + TestDesign.getDesignPartTypeName(this.getReference()
			    .getContainerTypeId()) + "\n");

	    buffer.append("Name: " + this.getName());
	    buffer.append("\nStep Container Id: " + this.getId());
	    buffer.append("\nDescription: "
		    + this.getReference().getDescription());
	    return buffer.toString();
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return null;
	}
    }

    @Override
    public T_test_stepcontainer getReference() {
	return m_reference;
    }

    private void setReference(T_test_stepcontainer reference) {
	if (reference == null) {
	    throw new NullPointerException();
	}
	m_reference = reference;
    }

    @Override
    public String getTypeName() {
	return TestDesign.getDesignPartTypeName(this.getReference()
		.getContainerTypeId());
    }

    private int compare(Comparable source) {
	return Comparable.EXACT;
    }

    @Override
    public int compare(Comparable source, Comparable treeReference) {
	TestDesignTreeNode src = (TestDesignTreeNode) source;
	TestDesignTreeNode dest = (TestDesignTreeNode) treeReference;

	String srcCritical = src.getReference().getParameterValue(
		TestDesignTreeParameters.Critical.name());
	String srcRunalways = src.getReference().getParameterValue(
		TestDesignTreeParameters.RunAlways.name());
	String srcThread = src.getReference().getParameterValue(
		TestDesignTreeParameters.ThreadPoolSize.name());
	String srcInvoc = src.getReference().getParameterValue(
		TestDesignTreeParameters.InvocationCount.name());
	String srcSuccess = src.getReference().getParameterValue(
		TestDesignTreeParameters.SuccessPercentage.name());

	String destCritical = dest.getReference().getParameterValue(
		TestDesignTreeParameters.Critical.name());
	String destRunalways = dest.getReference().getParameterValue(
		TestDesignTreeParameters.RunAlways.name());
	String destThread = dest.getReference().getParameterValue(
		TestDesignTreeParameters.ThreadPoolSize.name());
	String destInvoc = dest.getReference().getParameterValue(
		TestDesignTreeParameters.InvocationCount.name());
	String destSuccess = dest.getReference().getParameterValue(
		TestDesignTreeParameters.SuccessPercentage.name());

	if ((srcCritical == null ? destCritical != null : !srcCritical
		.equals(destCritical))
		|| (srcRunalways == null ? destRunalways != null
			: !srcRunalways.equals(destRunalways))
		|| (srcThread == null ? destThread != null : !srcThread
			.equals(destThread))
		|| (srcInvoc == null ? destInvoc != null : !srcInvoc
			.equals(destInvoc))
		|| (srcSuccess == null ? destSuccess != null : !srcSuccess
			.equals(destSuccess))) {
	    return Comparable.DIFFERENT_PROPERTIES;
	}
	return compare(src.getObject());
    }

    private boolean hasSameStaticParameters(HashMap<String, Object> params,
	    Comparable treeReference) {
	String description = (String) params.get("description");
	String runAlways = (String) params.get("runAlways");
	String critical = (String) params.get("critical");
	String invocationCount = (String) params.get("invocationCount");
	String successPercentage = (String) params.get("successPercentage");
	String threadPoolSize = (String) params.get("threadPoolSize");
	LinkedList<String> labels = (LinkedList<String>) params.get("labels");

	TestDesignTreeNode testDesignTreeNode = (TestDesignTreeNode) treeReference;
	TestCaseRefined tcRefined = (TestCaseRefined) ((TestDesignTreeNode) testDesignTreeNode)
		.getObject();

	if (tcRefined != null) {
	    HashMap myLabels = tcRefined.getLabelsAsHashMap();
	    if (myLabels.size() != labels.size()) {
		return false;
	    }
	    Iterator iterator = myLabels.keySet().iterator();
	    while (iterator.hasNext()) {
		T_test_label myLabel = (T_test_label) myLabels.get(iterator
			.next());
		if (!labels.contains(myLabel.getName())) {
		    return false;
		}
	    }
	}
	String curCritical = testDesignTreeNode.getReference()
		.getParameterValue(TestDesignTreeParameters.Critical.name());
	String curRunalways = testDesignTreeNode.getReference()
		.getParameterValue(TestDesignTreeParameters.RunAlways.name());
	String curThread = testDesignTreeNode.getReference().getParameterValue(
		TestDesignTreeParameters.ThreadPoolSize.name());
	String curInvoc = testDesignTreeNode.getReference().getParameterValue(
		TestDesignTreeParameters.InvocationCount.name());
	String curSuccess = testDesignTreeNode.getReference()
		.getParameterValue(
			TestDesignTreeParameters.SuccessPercentage.name());

	if ((curCritical == null ? critical == null : curCritical
		.equals(critical))
		&& (curRunalways == null ? runAlways == null : curRunalways
			.equals(runAlways))
		&& (curThread == null ? threadPoolSize == null : curThread
			.equals(threadPoolSize))
		&& (curInvoc == null ? invocationCount == null : curInvoc
			.equals(invocationCount))
		&& (curSuccess == null ? successPercentage == null : curSuccess
			.equals(successPercentage))
		&& getReference().getDescription().equals(description)) {
	    return true;
	} else {
	    return false;
	}
    }

    public String[] getLabels() {
	List<String> labels = new LinkedList<String>();
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    Iterator it = getReference().t_test_labelpairs.getIterator();
	    while (it.hasNext()) {
		T_test_labelpairs value = (T_test_labelpairs) it.next();
		T_test_label label = handler.getLabelById(value.getLabelId());
		labels.add(label.getName());
	    }
	} else {
	    labels.add(DEFAULT_TYPE);
	}
	String[] result = new String[labels.size()];
	labels.toArray(result);
	return result;
    }

    public boolean hasLabel(String token) {
	boolean result = false;
	String[] labels = getLabels();
	for (int i = 0; i < labels.length; i++) {
	    if (labels[i].equals(token)) {
		result = true;
		break;
	    }
	}
	return result;
    }

    @Override
    public boolean compareParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return hasSameStaticParameters(params, treeTreference);
    }

    public boolean hasSameRunTimeParams(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return true;
    }

    public T_test_label[] getLabelsAsArray() {
	T_test_label[] labels = null;
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    labels = new T_test_label[labelpairs.length];
	    for (int i = 0; i < labelpairs.length; i++) {
		labels[i] = handler.getLabelById(labelpairs[i].getLabelId());
	    }
	}
	return labels;
    }

    public HashMap getLabelsAsHashMap() {
	HashMap result = new HashMap();
	LabelDataHandler handler = new LabelDataHandler();
	if (getReference().t_test_labelpairs != null
		&& getReference().t_test_labelpairs.size() > 0) {
	    T_test_labelpairs[] labelpairs = getReference().t_test_labelpairs
		    .toArray();
	    for (int i = 0; i < labelpairs.length; i++) {
		T_test_label label = handler.getLabelById(labelpairs[i]
			.getLabelId());
		result.put(label.getId(), label);
	    }
	}
	return result;
    }

    public String getLabelsAsString(boolean inheritance) {
	return LabelUtils
		.convertLabelsToString(getLabelsAsArray(), inheritance);
    }

    public boolean matchesLabelPattern(String regex) {
	return LabelUtils.matchesLabelPattern(regex, getLabelsAsString(true));
    }
}
